#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <assert.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <iostream>
#include <string>
#include <fstream>

bool read_file(const std::string &name,std::string &out)
{
    std::ifstream in(name,std::ios::binary);
    if(!in.is_open()) return false;

    in.seekg(0,std::ios::end);
    int fsize = in.tellg();
    in.seekg(0,std::ios::beg);
    out.resize(fsize);

    in.read(&out[0],fsize);
    in.close();
    return true;
}

int main()
{
    int listenfd = socket(AF_INET,SOCK_STREAM,0);
    
    struct sockaddr_in server;
    server.sin_family = AF_INET;
    server.sin_port = htons(9090);
    server.sin_addr.s_addr = INADDR_ANY;
    int n = bind(listenfd,(const sockaddr *)&server,sizeof(server));
    assert(n != -1);

    n = listen(listenfd,5);
    assert(n != -1);
    sleep(10);
    struct sockaddr_in client;
    socklen_t len = sizeof(client);


    for(int i=0;i<5;i++)// 一次能维护5个客户端连接
    {
        int sockfd = accept(listenfd,(sockaddr *)&client,&len);
        
        //1. 获取文件名长度
        char str_len[4] = {0};
        recv(sockfd,str_len,4,0);
        int len = 0;
        memcpy(&len,str_len,4);
        std::cout << "得到长度: " << len << std::endl;

        //2. 获取文件名
        int recv_len = 0;
        char file_name[len+1];
        while(recv_len < len)
        {
            int n = recv(sockfd,file_name,sizeof(file_name)-1,0);
            recv_len += n;
        }
        file_name[recv_len] = 0;
        std::cout << "得到文件名: " << file_name << std::endl; 

        //3. 根据文件名读取文件信息
        std::string file;
        bool ret = read_file(file_name,file);
        if(ret)
        {
            // 如果正确读取文件，响应
            char buffer[1024] = {0};
            int len = file.size();
            memcpy(buffer,&len,sizeof(len));
            sprintf(buffer+4,"%s",file.c_str());

            send(sockfd,buffer,sizeof(buffer)-1,0);
        }
    }
    close(listenfd);
    return 0;
}